package com.godenwater.recv.server.sl651;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.gov.mwr.sl651.HydroMessage;
import cn.gov.mwr.sl651.IMessageBody;
import cn.gov.mwr.sl651.IMessageHeader;
import cn.gov.mwr.sl651.Symbol;
import cn.gov.mwr.sl651.body.Up2FBody;
import cn.gov.mwr.sl651.body.Up30Body;
import cn.gov.mwr.sl651.body.UpBaseBody;
import cn.gov.mwr.sl651.utils.ByteUtil;

/**
 * 报文解码类，作为上行报文的解码类，此类必须实现对所有消息体的封闭细节
 * 
 * @ClassName: YfServerDataDecoder
 * @Description: TODO
 * @author lipujun
 * @date Mar 2, 2013
 * 
 */
public class ServerDataDecoder implements ProtocolDecoder {
	private static final AttributeKey BUF_BYTE = new AttributeKey(
			ServerDataDecoder.class, "BUF_KEY");

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
			throws Exception {
		// TODO Auto-generated method stub
		try {

			int bufLength = 0;

			IoBuffer buffer = null;
			byte[] buf = (byte[]) session.getAttribute(BUF_BYTE);
			if (buf == null) {
				bufLength = in.remaining();
				buffer = in;
			} else {
				bufLength = buf.length + in.remaining();
				System.out.println(" 有粘包数据出现  ");
				buffer = IoBuffer.allocate(buf.length + in.remaining());
				buffer.setAutoExpand(true);
				buffer.put(buf);
				buffer.put(in);
				buffer.flip();
			}

			logger.info("解析报文，接收到报文，报文长度为 " + bufLength + " 个字节!");

			// while (buffer.remaining() >= 0) {// 循环处理数据包
			// //
			// int dataLen = buffer.getInt(buffer.position());
			// byte[] b = new byte[dataLen];
			// buffer.get(b);
			// SMPPPacket pak = null;
			// int id = -1;
			// id = SMPPIO.bytesToInt(b, 4, 4);
			// pak = PacketFactory.newInstance(id);
			// if (pak != null) {
			// pak.readFrom(b, 0);
			// out.write(pak);
			// }
			byte[] mode = new byte[1];
			buffer.get(mode);

			IMessageHeader header;
			if (mode[0] == Symbol.SOH_ASC) {
				header = new cn.gov.mwr.sl651.header.AscHeader();
				header.setStartBit(new byte[] { mode[0] });
			} else {
				header = new cn.gov.mwr.sl651.header.HexHeader();
				byte[] startBit = new byte[1];
				buffer.get(startBit);
				header
						.setStartBit(new byte[] { Symbol.SOH_HEX,
								Symbol.SOH_HEX });
			}

			// byte[] startBit = new byte[header.getStartBitLen()];
			// buffer.get(startBit);

			// 上行的，中心站地址在前
			byte[] centerAddr = new byte[header.getCenterAddrLen()];
			buffer.get(centerAddr);
			header.setCenterAddr(centerAddr);

			// 上行的，遥测站地址在前
			byte[] stationAddr = new byte[header.getStationAddrLen()];
			buffer.get(stationAddr);
			header.setStationAddr(stationAddr);

			byte[] password = new byte[header.getPasswordLen()];
			buffer.get(password);
			header.setPassword(password);
			//
			byte[] funcCode = new byte[header.getFuncCodeLen()];
			buffer.get(funcCode);
			header.setFuncCode(funcCode);

			byte[] bodyLength = new byte[header.getBodySizeLen()];
			buffer.get(bodyLength);
			header.setBodySize(bodyLength);

			byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
			buffer.get(bodyStartBit);
			header.setBodyStartBit(bodyStartBit);

			if (bodyStartBit[0] == Symbol.SYN) {
				byte[] bodyCount = new byte[header.getBodyCountLen()];
				buffer.get(bodyCount);
				header.setBodyCount(bodyCount);
			}

			// 转换报文中的上下行标识及报文长度
			int bodyLengthLen = parseLength(bodyLength);// 需要考虑拆分字节;
			byte[] bodyContent = new byte[bodyLengthLen];// 根据前面header的内容来获取长度
			buffer.get(bodyContent);

			// 终止符
			byte[] eof = new byte[1];
			buffer.get(eof);

			// 校验码
			byte[] crc;
			if (mode[0] == Symbol.SOH_ASC) {
				crc = new byte[4];
			} else {
				crc = new byte[2];

			}
			buffer.get(crc);

			// 组装消息
			HydroMessage message = new HydroMessage();
			message.setHeader(header);

			// 根据功能码，构建body体
			IMessageBody body = new UpBaseBody();;
			body.setContents(bodyContent);
			message.setBody(body);
//			if (funcCode[0] == 0x2F) {
//				body = new Up2FBody();
//				body.setContents(bodyContent);
//				message.setBody(body);
//			} else {
//				body = new Up30Body();
//				body.setContents(bodyContent);
//				message.setBody(body);
//			}
			
			message.setEOF(eof[0]);
			message.setCRC(crc);

			out.write(message);

			// }
			if (buffer.hasRemaining()) {// 如果有剩余的数据，则放入Session中
				byte[] tmpb = new byte[buffer.remaining()];
				buffer.get(tmpb);
				session.setAttribute(BUF_BYTE, tmpb);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 获取报文长度，第一个字节的高四位表示上下行标识，故需要进行“与计算”
	 * 
	 * @param bodyLen
	 * @return
	 */
	private int parseLength(byte[] bodyLen) {
		byte A1 = (byte) (bodyLen[0] & 0x0f);
		byte A2 = bodyLen[1];
		return ByteUtil.bytesToUshort(new byte[] { A1, A2 });
	}

	public void dispose(IoSession session) throws Exception {
		// TODO Auto-generated method stub

	}

	public void finishDecode(IoSession session, ProtocolDecoderOutput out)
			throws Exception {
		// TODO Auto-generated method stub

	}

}
